package cn.autumnorange.app.common.provider.cacheannotation.aop;

import cn.autumnorange.app.common.consumerproducer.util.AnnotationUtil;
import org.aopalliance.aop.Advice;
import org.redisson.api.RedissonClient;
import org.springframework.aop.ClassFilter;
import org.springframework.aop.MethodMatcher;
import org.springframework.aop.Pointcut;
import org.springframework.aop.support.AbstractPointcutAdvisor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import java.lang.annotation.Annotation;

@Component
public class CachePointcutAdvisor extends AbstractPointcutAdvisor {
  private ApplicationContext applicationContext;

  private volatile RedisMethodInterceptor redisMethodInterceptor = null;

  @Value("${ribbon.ConnectTimeout}")
  private long connectTimeout;

  @Value("${ribbon.ReadTimeout}")
  private long readTimeout;
  //    当前节点的最大重试次数，不包括首次调用
  //    @Value("${ribbon.MaxAutoRetries}")
  //    private int maxAutoRetries;
  //    //   重试负载均衡其他节点的最大重试次数，不包括首次server
  //    @Value("${ribbon.MaxAutoRetriesNextServer}")
  //    private int maxAutoRetriesNextServer;
  // spring ApplicationContext 全局实例上下文会自动注入
  public CachePointcutAdvisor(ApplicationContext applicationContext) {
    this.applicationContext = applicationContext;
    //        RpcidAnnotationnStrategy rpcidAnnotationnStrategy =
    //                new RpcidAnnotationnStrategy(
    //                        applicationContext,
    //                        connectTimeout,
    //                        readTimeout,
    //                        maxAutoRetries,
    //                        maxAutoRetriesNextServer);

    //        annotationContext.putAnnotationStrategy(
    //                RPCIdempotentLockTarget.class.getName(), rpcidAnnotationnStrategy);

    // 参数
    //          java.lang.Object argument = arguments[index];
  }
  @Override
  public Pointcut getPointcut() {
    return new Pointcut() {
      @Override
      public ClassFilter getClassFilter() {
        return (Class<?> clazz) -> AnnotationUtil.existsAnnotation(clazz, org.springframework.stereotype.Service.class);
      }

      @Override
      public MethodMatcher getMethodMatcher() {
        return MethodMatcher.TRUE;
      }
    };
  }

  @Override
  public Advice getAdvice() {
    if (redisMethodInterceptor == null) {
      synchronized (RedisMethodInterceptor.class) {
        if (redisMethodInterceptor == null) {
          redisMethodInterceptor =
              new RedisMethodInterceptor(
                  applicationContext.getBean(RedissonClient.class), connectTimeout, readTimeout);
        }
      }
    }
    return redisMethodInterceptor;
  }


}
